/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import lombok.AllArgsConstructor;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.tool.api.R;
import org.springblade.modules.admin.dto.CheckPlanSetTimeDTO;
import org.springblade.modules.admin.enums.PlanOverdueEnum;
import org.springblade.modules.admin.vo.MaintainPlanStatisticsVO;
import org.springblade.modules.admin.dto.*;
import org.springblade.modules.admin.entity.MaintainPlanCheck;
import org.springblade.modules.admin.entity.MaintainPlanContent;
import org.springblade.modules.admin.enums.MaintainPlanContentEnum;
import org.springblade.modules.admin.enums.TaskStatusEnum;
import org.springblade.modules.admin.service.IMaintainPlanContentService;
import org.springblade.modules.admin.vo.MaintainPlanPageVO;
import org.springblade.modules.admin.vo.check.ProblemPlanVo;
import org.springblade.modules.admin.vo.check.ProblemResultVo;
import org.springblade.modules.admin.vo.check.ProblemSearchVo;
import org.springblade.modules.admin.vo.check.ProblemStatusVo;
import org.springblade.modules.admin.vo.plan.CheckChildPlanVo;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.modules.admin.vo.MaintainPlanCheckVO;
import org.springblade.modules.admin.service.IMaintainPlanCheckService;
import org.springblade.core.boot.ctrl.BladeController;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 质检工单表 Controller
 *
 * @author ysq
 * @since 2023-11-27
 */
@RestController
@AllArgsConstructor
@RequestMapping("admin/plan/check")
@Api(value = "质检工单表", tags = "质检工单表接口")
public class MaintainPlanCheckController extends BladeController {

	private final IMaintainPlanCheckService maintainPlanCheckService;

	private final IMaintainPlanContentService maintainPlanContentService;
	// 紧急程度
	private final Integer[] emerProcTypes = {0, 1, 2, 3, 4};

	/**
	 * 批量新增 质检工单及其关联业务
	 * 2023-11-27 版本：优先级 1
	 *
	 * @param maintainPlanCheckBatchDTO 质检工单批量新增DTO
	 * @return 是否新增成功
	 */
	@PostMapping("/addBatch")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "批量新增", notes = "传入maintainPlanCheckBatchDTO")
	public R<Long> addBatch(@Valid @RequestBody MaintainPlanCheckBatchDTO maintainPlanCheckBatchDTO) {
		if (maintainPlanCheckBatchDTO.getUserIds() == null) {
			maintainPlanCheckBatchDTO.setUserIds(new ArrayList<>(0));
		}
		return R.data(maintainPlanCheckService.addBatch(maintainPlanCheckBatchDTO));
	}

	/**
	 * 通过id查询质检工单详情
	 * 2023-11-28 版本：优先级 1
	 *
	 * @param planId 质检工单id
	 * @return 质检工单详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 31)
	@ApiOperation(value = "详情", notes = "传入maintainPlanCheck")
	public R<MaintainPlanCheckVO> detail(Long planId) {
		MaintainPlanCheckVO maintainPlanCheckVO = maintainPlanCheckService.selectMaintainPlanDetailById(planId);
		return R.data(maintainPlanCheckVO);
	}

	/**
	 * 分页 质检工单列表
	 * 2023-11-28 版本：优先级 1 尚未绑定维修/事务 工单
	 *
	 * @param maintainPlanCheckDTO 质检工单
	 * @return 质检工单分页
	 */
	@PostMapping("/page")
	@ApiOperationSupport(order = 32)
	@ApiOperation(value = "分页", notes = "传入maintainPlanCheck")
	public R<IPage<MaintainPlanPageVO>> page(@RequestBody MaintainPlanCheckPageDTO maintainPlanCheckDTO) {
		IPage<MaintainPlanPageVO> pages = maintainPlanCheckService.pageByCondition(maintainPlanCheckDTO);
		return R.data(pages);
	}

	/**
	 * 当前租户质检工单状态列表抬头统计
	 *
	 * @return 质检工单状态列表抬头统计结果
	 */
	@GetMapping("/statistics")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "统计", notes = "质检工单状态列表抬头统计,无参数传入")
	public R<MaintainPlanStatisticsVO> statistics() {
		return R.data(maintainPlanCheckService.statistics());
	}


	@GetMapping("/getProblemStatus")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "问题点状态统计")
	public R<ProblemStatusVo> getProblemStatus() {
		return R.data(maintainPlanCheckService.getProblemStatus());
	}


	@GetMapping("/getChildPlanDetail")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "列表子工单详情")
	public R<CheckChildPlanVo> getChildPlanDetail(Long planId) {
		return R.data(maintainPlanCheckService.getCheckChildPlanVo(planId));
	}


	@GetMapping("/getPlanListOfUserId")
	@ApiOperationSupport(order = 33)
	@ApiOperation(value = "人员离职进行中工单")
	public R<List<MaintainPlanPageVO>> getPlanListOfUserId(String userId) {
		return R.data(maintainPlanCheckService.getPlanListOfUserId(userId));
	}


	@PostMapping("/down/oroblem")
	@ApiOperationSupport(order = 34)
	@ApiOperation(value = "问题点导出")
	public void downProblemList(HttpServletResponse response, @RequestBody ProblemSearchVo problemSearchVo) throws IOException {
		List<ProblemPlanVo> problemPlanVos = maintainPlanCheckService.downProblemList(problemSearchVo);
		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("项目名称", "电梯位置", "任务编号",
				"完成时间", "电梯部件", "问题分类", "问题描述", "问题原因", "问题归属", "紧急程度", "创建人", "创建时间", "问题处理状态", "调度人", "整改工单", "整改结果", "来源任务", "任务来源"
			);
			rows.add(title);
			for (ProblemPlanVo problemPlanVo : problemPlanVos) {
				List<String> row = new ArrayList<>();
				row.add(problemPlanVo.getBuildingName());
				row.add(problemPlanVo.getElevatorAddress());
				row.add(problemPlanVo.getCheckPlanId().toString());
				row.add(DateUtil.format(problemPlanVo.getPlanEndTime(), "yyyy-MM-dd HH:mm:ss"));
				row.add(Convert.toStr(problemPlanVo.getPartNames(), ""));
				row.add(Convert.toStr(problemPlanVo.getFaultReasonClassifiedName(), ""));
				row.add(Convert.toStr(problemPlanVo.getDisposeDesc(), ""));
				row.add(Convert.toStr(problemPlanVo.getFaultReasonName(), ""));
				row.add(Convert.toStr(problemPlanVo.getFaultReasonWhoName(), ""));
				//1:非常紧急2:紧急3:普通4:较低
				if (problemPlanVo.getEmerProcType().equals(emerProcTypes[1])) {
					row.add("非常紧急");
				} else if (problemPlanVo.getEmerProcType().equals(emerProcTypes[2])) {
					row.add("紧急");
				} else if (problemPlanVo.getEmerProcType().equals(emerProcTypes[3])) {
					row.add("普通");
				} else if (problemPlanVo.getEmerProcType().equals(emerProcTypes[4])) {
					row.add("较低");
				} else {
					row.add("/");
				}
				row.add(Convert.toStr(problemPlanVo.getCreateUserName(), ""));
				row.add(Convert.toStr(DateUtil.format(problemPlanVo.getCreateTime(), "yyyy-MM-dd HH:mm:ss"), ""));
				if (problemPlanVo.getChildPlanId() == null) {
					row.add(Convert.toStr("未处理"));
				} else {
					row.add(Convert.toStr("已处理"));
				}
				row.add(Convert.toStr(problemPlanVo.getUserName(), ""));
				if (problemPlanVo.getChildPlanId() == null) {
					row.add(Convert.toStr("0"));
				} else {
					row.add(Convert.toStr("1"));
				}
				if (problemPlanVo.getPlanStatus() == null) {
					row.add(Convert.toStr("/"));
				} else if (problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_UNDER_WAY.getStatus()) {
					row.add(Convert.toStr("整改中"));
				} else if (problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_SIGN_FINISH.getStatus()) {
					row.add(Convert.toStr("整改完成"));
				} else {
					if (problemPlanVo.getChildTypeStatus() == MaintainPlanContentEnum.MAINTAIN_WX.getId()) {
						if (problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_ALLOCATION.getStatus() || problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_PENDING.getStatus() || problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_TO_START.getStatus()) {
							row.add(Convert.toStr("待整改"));
						} else if (problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_CLOSED.getStatus() || problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_TURN_DOWN.getStatus() || problemPlanVo.getPlanStatus() == TaskStatusEnum.WX_CHECK_PASS_CLOSED.getStatus()) {
							row.add(Convert.toStr("已关闭"));
						}
					} else if (problemPlanVo.getChildTypeStatus() == MaintainPlanContentEnum.MAINTAIN_AFFAIR.getId()) {
						if (problemPlanVo.getPlanStatus() == TaskStatusEnum.ZJ_CLOSED.getStatus()) {
							row.add(Convert.toStr("已关闭"));
						}else if(problemPlanVo.getPlanStatus() == TaskStatusEnum.ZJ_ALLOCATION.getStatus()||problemPlanVo.getPlanStatus() == TaskStatusEnum.ZJ_TO_START.getStatus()){
							row.add(Convert.toStr("待整改"));
						}
					} else {
						row.add(Convert.toStr("/"));
					}
				}

				if (problemPlanVo.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_WX.getId()) {
					row.add(Convert.toStr("维修任务"));
					row.add(Convert.toStr("维修评分"));
				} else if (problemPlanVo.getTypeStatus() == MaintainPlanContentEnum.MAINTAIN_CHECK.getId()) {
					row.add(Convert.toStr("质检任务"));
					row.add(Convert.toStr("质检工单"));
				} else {
					row.add(Convert.toStr("/"));
					row.add(Convert.toStr("/"));
				}
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}


	/**
	 * 质检工单 Excel导出
	 * 2023-11-28 版本：优先级 1
	 *
	 * @param maintainPlanCheckDTO 查询条件
	 */
	@PostMapping("/down/excel")
	@ApiOperationSupport(order = 34)
	@ApiOperation(value = "导出", notes = "传入maintainPlanCheck")
	public void export(@RequestBody MaintainPlanCheckPageDTO maintainPlanCheckDTO, HttpServletResponse response) throws IOException {
		// 以下使用复用的Excel导出方法

		// 根据条件查询质检工单列表，导出数据源
		List<MaintainPlanPageVO> listVoList;
		//表示离职人员
		Integer isUserStatus = 1;
		if (Convert.toInt(maintainPlanCheckDTO.getIsUserStatus(), -1).equals(isUserStatus)) {
			listVoList = maintainPlanCheckService.getPlanListOfUserId(maintainPlanCheckDTO.getPlanUserId());
		} else {
			listVoList = maintainPlanCheckService.listByCondition(maintainPlanCheckDTO);
		}

		ExcelWriter excelWriter = null;
		ServletOutputStream outputStream = response.getOutputStream();
		try {
			List<List<String>> rows = new ArrayList<>();
			List<String> title = CollUtil.newArrayList("项目名称", "电梯位置", "任务编号",
				"任务类型", "执行人", "创建人", "创建时间", "执行时间",
				"开始时间", "完成时间", "任务耗时(分钟)",
				"质检结果", "质检问题", "整改工单数",
				"紧急程度", "任务状态"
			);
			rows.add(title);
			for (MaintainPlanPageVO maintainPlanCheckVO : listVoList) {
				Integer checkType = Convert.toInt(maintainPlanCheckVO.getCheckType(), 1);
				String checkTypeName = "保养质检";
				if (checkType == 1) {
					checkTypeName = "保养质检";
				} else if (checkType == 2) {
					checkTypeName = "重复故障质检";
				} else if (checkType == 3) {
					checkTypeName = "维保移交质检";
				} else if (checkType == 4) {
					checkTypeName = "安装移交质检";
				} else if (checkType == 5) {
					checkTypeName = "常规质检";
				} else if (checkType == 6){
					checkTypeName = "维修质检";
				}
				List<String> row = new ArrayList<>();
				row.add(maintainPlanCheckVO.getBuildingName());
				row.add(maintainPlanCheckVO.getElevatorAddress());
				row.add(maintainPlanCheckVO.getPlanId().toString());
				row.add(checkTypeName);
				row.add(Convert.toStr(maintainPlanCheckVO.getUserNames(), ""));
				row.add(Convert.toStr(maintainPlanCheckVO.getCreateName(), ""));
				row.add(DateUtil.format(maintainPlanCheckVO.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
				row.add(DateUtil.format(maintainPlanCheckVO.getPlanDate(), "yyyy-MM-dd"));
				row.add(Convert.toStr(DateUtil.format(maintainPlanCheckVO.getPlanBeginTime(), "yyyy-MM-dd HH:mm:ss"), "/"));
				row.add(Convert.toStr(DateUtil.format(maintainPlanCheckVO.getPlanBeginTime(), "yyyy-MM-dd HH:mm:ss"), "/"));
				row.add(Convert.toStr(maintainPlanCheckVO.getWorkMinute(), "/"));

				row.add(Convert.toStr(
					new Integer("1").equals(maintainPlanCheckVO.getCheckStatus()) ? "通过"
						: (new Integer("2").equals(maintainPlanCheckVO.getCheckStatus()) ? "不通过"
						: "")
					, ""
				));

				row.add(Convert.toStr(maintainPlanCheckVO.getProblemCounts(), "0"));
				row.add(Convert.toStr(maintainPlanCheckVO.getChildCounts(), "0"));

				//1:非常紧急2:紧急3:普通4:较低
				if (maintainPlanCheckVO.getEmerProcType().equals(emerProcTypes[1])) {
					row.add("非常紧急");
				} else if (maintainPlanCheckVO.getEmerProcType().equals(emerProcTypes[2])) {
					row.add("紧急");
				} else if (maintainPlanCheckVO.getEmerProcType().equals(emerProcTypes[3])) {
					row.add("普通");
				} else if (maintainPlanCheckVO.getEmerProcType().equals(emerProcTypes[4])) {
					row.add("较低");
				} else {
					row.add("/");
				}
				row.add(TaskStatusEnum.getTaskName(MaintainPlanContentEnum.MAINTAIN_CHECK.getId(), maintainPlanCheckVO.getPlanStatus()));
				rows.add(row);
			}
			String fileName = DateUtil.format(new Date(), "yyyyMMddHHmmss") + ".xlsx";
			setResponseHeader(response, fileName);
			excelWriter = ExcelUtil.getBigWriter(rows.size());
			excelWriter.write(rows, true);
			excelWriter.flush(outputStream, true);
		} catch (
			Exception e) {
			e.printStackTrace();
		} finally {
			if (excelWriter != null) {
				excelWriter.close();
			}
			outputStream.close();
		}
	}

	/**
	 * 批量任务指派/转派
	 * 2023-11-29 版本：优先级 1
	 *
	 * @return 是否修改成功
	 */
	@PostMapping("/assign")
	@ApiOperationSupport(order = 40)
	@ApiOperation(value = "批量任务指派/转派")
	public R<Boolean> assign(@RequestBody CheckPlanSendDTO checkPlanSendDTO) {
		return R.data(maintainPlanCheckService.assign(checkPlanSendDTO));
	}

	/**
	 * 单个任务更新
	 * 2023-11-30 版本：优先级 1, 与事务工单基本一致
	 *
	 * @return 是否更新成功
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 41)
	@ApiOperation(value = "单个任务更新")
	public R<Boolean> update(@RequestBody MaintainPlanCheckUpdateDTO maintainPlanCheckDTO) {
		// 获取相关信息并执行更新
		Long elevatorId = maintainPlanCheckDTO.getElevatorId();
		MaintainPlanCheck current = maintainPlanCheckService.getOne(new LambdaQueryWrapper<MaintainPlanCheck>()
			.eq(MaintainPlanCheck::getPlanId, maintainPlanCheckDTO.getPlanId())
			.eq(BaseEntity::getIsDeleted, 0)
		);
		if (elevatorId != null) {
			MaintainPlanCheck maintainPlanCheck = maintainPlanCheckService.getById(current.getId());
			MaintainPlanContent maintainPlanContent = maintainPlanContentService.getById(maintainPlanCheck.getPlanId());
			maintainPlanContent.setElevatorId(elevatorId);
			maintainPlanContentService.updateById(maintainPlanContent);
		}
		// 除了elevatorId, 其它字段设置进入maintainPlanCheck
		MaintainPlanCheck maintainPlanCheck = new MaintainPlanCheck();
		maintainPlanCheck.setId(current.getId());
		maintainPlanCheck.setPlanDesc(maintainPlanCheckDTO.getPlanDesc());
		maintainPlanCheck.setExtWordUrl(mapListToJson(maintainPlanCheckDTO.getExtWordUrl()));
		maintainPlanCheck.setOtherUrl(mapListToJson(maintainPlanCheckDTO.getOtherUrl()));
		maintainPlanCheck.setEmerProcType(maintainPlanCheckDTO.getEmerProcType());
		maintainPlanCheck.setCheckStatus(maintainPlanCheckDTO.getCheckStatus());
		maintainPlanCheck.setCheckType(maintainPlanCheckDTO.getCheckType());
		return R.data(maintainPlanCheckService.updateById(maintainPlanCheck));
	}

	/**
	 * 批量任务关闭
	 * 2023-11-29 版本：优先级 1
	 *
	 * @return 是否关闭成功
	 */
	@PostMapping("/close")
	@ApiOperationSupport(order = 41)
	@ApiOperation(value = "批量任务关闭")
	public R<Boolean> close(@RequestBody CheckPlanCloseDTO checkPlanCloseDTO) {
		return R.data(maintainPlanCheckService.closeBatch(checkPlanCloseDTO));
	}

	/**
	 * 批量设置执行时间
	 * 2023-11-29 版本：优先级 1
	 *
	 * @return 是否设置成功
	 */
	@PostMapping("/setExecuteTime")
	@ApiOperationSupport(order = 42)
	@ApiOperation(value = "批量设置执行时间")
	public R<Boolean> setExecuteTime(@RequestBody CheckPlanSetTimeDTO checkPlanSetTimeDTO) {
		return R.data(maintainPlanCheckService.setExecuteTime(checkPlanSetTimeDTO));
	}


	@GetMapping("getCheckChildPlanList")
	@ApiOperation(value = "获取关联工单")
	public R<List<CheckChildPlanVo>> getCheckChildPlanList(Long planId, Integer typeStatus) {
		return R.data(maintainPlanCheckService.getCheckChildPlanList(planId, typeStatus));
	}


	@PostMapping("getProblemResultList")
	@ApiOperation(value = "质检工单问题点列表")
	public R<IPage<ProblemResultVo>> getProblemResultList(@RequestBody ProblemSearchVo problemSearchVo) {

		return R.data(maintainPlanCheckService.getProblemResultList(problemSearchVo));
	}


	/**
	 * 功能描述: 发送响应流方法
	 */
	private void setResponseHeader(HttpServletResponse response, String fileName) {
		try {
			try {
				fileName = new String(fileName.getBytes(), "ISO8859-1");
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
			response.setContentType("application/octet-stream;charset=ISO8859-1");
			response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
			response.addHeader("Pargam", "no-cache");
			response.addHeader("Cache-Control", "no-cache");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	/**
	 * 当前Service Map List转 Json String方法
	 */
	private String mapListToJson(List<Map<String, String>> listMap) {
		if (listMap == null || listMap.isEmpty()) {
			// 返回一个新的Json空串
			return "[]";
		}
		return JSON.toJSONString(listMap);
	}


}
